use serde::{Serialize, Deserialize};
use std::collections::HashMap;
use crate::workflow::errors::WorkflowError;

/// Represents a complete workflow definition including source, transforms, and sink.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WorkflowDefinition {
    /// Unique identifier for the workflow
    pub id: String,
    /// Human-readable name of the workflow
    pub name: String,
    /// Source configuration for data ingestion
    pub source: SourceDefinition,
    /// List of transformation steps
    pub transforms: Vec<TransformDefinition>,
    /// Sink configuration for data output
    pub sink: SinkDefinition,
    /// Additional configuration parameters
    pub config: HashMap<String, String>,
}

impl WorkflowDefinition {
    /// Creates a new workflow definition from YAML content
    pub fn from_yaml(content: &str) -> Result<Self, WorkflowError> {
        serde_yaml::from_str(content).map_err(|e| WorkflowError::SerializationError(e))
    }

    /// Validates the workflow definition
    pub fn validate(&self) -> Result<(), WorkflowError> {
        // Basic validation
        if self.id.is_empty() {
            return Err(WorkflowError::InvalidConfig("Workflow ID cannot be empty".into()));
        }
        if self.name.is_empty() {
            return Err(WorkflowError::InvalidConfig("Workflow name cannot be empty".into()));
        }
        Ok(())
    }
}

/// Defines how data is ingested into the workflow
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SourceDefinition {
    /// Type of the source (e.g., "kafka", "file", etc.)
    pub kind: String,
    /// Source-specific configuration
    pub config: HashMap<String, String>,
}

/// Defines how data is transformed within the workflow
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TransformDefinition {
    /// Type of the transformation
    pub kind: String,
    /// Transform-specific configuration
    pub config: HashMap<String, String>,
}

/// Defines how data is output from the workflow
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SinkDefinition {
    /// Type of the sink (e.g., "kafka", "file", etc.)
    pub kind: String,
    /// Sink-specific configuration
    pub config: HashMap<String, String>,
}

#[derive(Debug, Clone)]
pub struct NewStep {
    pub id: String,
    pub config: NewStepConfig,
}

#[derive(Debug, Clone)]
pub struct NewStepConfig {
    pub parameter: String,
} 